package main

import (
	"chinaport-proxy/client"
	"chinaport-proxy/config"
	"chinaport-proxy/handlers"
	"chinaport-proxy/middleware"
	"chinaport-proxy/services"
	"context"
	"flag"
	"fmt"
	"log/slog"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
)

// Build variables (set via ldflags)
var (
	Version   = "dev"
	Commit    = "unknown"
	BuildTime = "unknown"
)

func main() {
	// Command line flags
	var (
		configPath = flag.String("config", "config.json", "Path to configuration file")
		version    = flag.Bool("version", false, "Show version information")
	)
	flag.Parse()

	// Show version if requested
	if *version {
		fmt.Printf("China E-Port UKey Proxy\n")
		fmt.Printf("Version:    %s\n", Version)
		fmt.Printf("Commit:     %s\n", Commit)
		fmt.Printf("Build Time: %s\n", BuildTime)
		os.Exit(0)
	}

	// Load configuration
	cfg, err := config.LoadConfig(*configPath)
	if err != nil {
		slog.Error("Failed to load configuration", "error", err, "path", *configPath)
		os.Exit(1)
	}

	// Configure logging
	var logLevel slog.Level
	if cfg.Log.Verbose {
		logLevel = slog.LevelDebug
	} else {
		logLevel = slog.LevelInfo
	}

	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		Level: logLevel,
	}))
	slog.SetDefault(logger)

	// Set Gin mode based on verbose flag
	if cfg.Log.Verbose {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}

	// Create UKey client with password from config (hardcoded 30s timeout)
	ukeyClient := client.NewUKeyClient(cfg.UKey.URL, 30*time.Second, cfg.UKey.Password)
	defer func() {
		if err := ukeyClient.Close(); err != nil {
			slog.Error("Failed to close UKey client", "error", err)
		}
	}()

	// Create handler with password from config
	handler := handlers.NewProxyHandler(ukeyClient, cfg.UKey.Password)

	// Create webhook service if configured
	if cfg.Webhook.FailureURL != "" || cfg.Webhook.AuditURL != "" {
		webhookService := services.NewWebhookService(cfg.Webhook.FailureURL, cfg.Webhook.AuditURL, cfg.Auth.AppSecret)
		handler.SetWebhookService(webhookService)

		// Also set webhook service for UKey client
		ukeyClient.SetWebhookService(webhookService)

		if cfg.Webhook.FailureURL != "" {
			slog.Info("Failure webhook enabled", "url", cfg.Webhook.FailureURL)
		}
		if cfg.Webhook.AuditURL != "" {
			slog.Info("Audit webhook enabled", "url", cfg.Webhook.AuditURL)
		}
	} else {
		slog.Info("Webhook notifications disabled")
	}

	// Setup Gin router
	router := gin.Default()

	// Add authentication middleware if app_secret is configured
	if cfg.Auth.AppSecret != "" {
		slog.Info("Authentication enabled")
		router.Use(middleware.AuthMiddleware(cfg.Auth.AppSecret))
	} else {
		slog.Info("Authentication disabled (no app_secret configured)")
	}

	// RPC endpoint
	router.POST("/rpc", handler.HandleRPC)

	// High-level API endpoints
	router.POST("/api/customs179", handler.HandleCustoms179)
	router.POST("/api/ceb/sign", handler.HandleCEBSign)

	// Create HTTP server with proper configuration
	addr := fmt.Sprintf(":%s", cfg.Server.Port)
	srv := &http.Server{
		Addr:    addr,
		Handler: router,
	}

	// Start server in a goroutine
	go func() {
		slog.Info("Starting China E-Port proxy server",
			"version", Version,
			"address", addr,
			"ukey_url", cfg.UKey.URL,
			"verbose", cfg.Log.Verbose,
			"config", *configPath,
		)

		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			slog.Error("Failed to start server", "error", err)
			os.Exit(1)
		}
	}()

	// Setup signal handling for graceful shutdown
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	// Wait for interrupt signal
	sig := <-quit
	slog.Info("Received shutdown signal", "signal", sig)

	// Create a deadline context for shutdown (hardcoded 10 seconds)
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// Attempt graceful shutdown
	slog.Info("Shutting down HTTP server")
	if err := srv.Shutdown(ctx); err != nil {
		slog.Error("Server forced to shutdown", "error", err)
	} else {
		slog.Info("Server shutdown completed")
	}
}
